package com.projectframe.base.db.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

@Repository("baseDao")
public class BaseDaoCommon extends HibernateDaoSupport
{
    protected final Logger log = Logger.getLogger(this.getClass());

    public <T> T findByPk(final Class<?> refClass, final Serializable key)
    {
        return load(refClass, key);
    }

    @SuppressWarnings("unchecked")
    public <T> T load(final Class<?> refClass, final Serializable key)
    {
        // Leon: 不直接用 HibernateTemplate.load, 因為它會拋出 ObjectNotFoundException 給外面
        // 改成如果真的 ObjectNotFoundException, 就回傳 null
        return (T)this.getHibernateTemplate().execute(new HibernateCallback<Object>()
        {
            public Object doInHibernate(final Session session)
            {
                try
                {
                    return session.get(refClass, key);
                }
                catch (ObjectNotFoundException e)
                {
                    return null;
                }
            }
        });
    }

    public List<?> findByExample(final Object model)
    {
        return this.getHibernateTemplate().findByExample(model);
    }
    
    /**
     * 示例：
     * User u = new User();    
     * u.setPassword("123");//必须 符合的条件但是这两个条件时并列的（象当于sql中的and）
     * u.setName("bb");  
     * list=this.getHibernateTemplate().findByExample(u,start,max);    
     * 返回：满足用户名为bb密码为123，自start起共max个User对象。（对象从0开始计数）
     *                         
     * @param model
     * @param start
     * @param count
     * @return 
     */
    public List<?> findByExample(final Object model, int start, int count)
    {
        return this.getHibernateTemplate().findByExample(model, start, count);
    }
    
    public List<?> findByCriteria(Class<?> clazz, List<Criteria> params, int firstResult, int maxResults)
    {
        DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
        
        if(maxResults>0)
            return this.getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
        else
            return this.getHibernateTemplate().findByCriteria(criteria);
    }

    //======================================================================
    //Insert
    //======================================================================

    public <T> T insertData(final T model, final boolean flushFlag)
    {
        this.getHibernateTemplate().save(model);
        
        if (flushFlag)
            flushData();
        
        return model;
    }

    public <T> T insertData(final T model)
    {
        return insertData(model, false);
    }
    
    //======================================================================
    //Update
    //======================================================================
    
    public <T> T updateData(final T model, final boolean flushFlag)
    {
        this.getHibernateTemplate().update(model);
        
        if(flushFlag)
            flushData();
        
        return model;
    }

    public <T> T updateData(final T model)
    {
        return updateData(model, false);
    }
    
    //======================================================================
    //Delete
    //======================================================================
    
    public void deleteData(Object model, final boolean flushFlag)
    {
        this.getHibernateTemplate().delete(model);
        
        if(flushFlag)
            flushData();
    }

    public void deleteData(Object model)
    {
        deleteData(model, false);
    }
    
    public void deleteDataAll(Collection<?> entities)
    {
        this.getHibernateTemplate().deleteAll(entities);
    }
    
    //======================================================================
    //Flush
    //====================================================================== 

    public void flushData()
    {
        this.getHibernateTemplate().flush();
    }
    
    @Autowired
    public void registerSessionFactory(SessionFactory sessionFactory)
    {
        super.setSessionFactory(sessionFactory);
        getHibernateTemplate().setFlushMode(HibernateTemplate.FLUSH_EAGER);
    }
}
